全局执行计划缓存

本文介绍了PolarDB PostgreSQL版(兼容Oracle)的全局执行计划缓存(Global Plan Cache)功能。

背景信息

在之前的PolarDB中,执行计划缓存(Plan Cache)是和Prepared Statement进行绑定的,这种做法存在以下两个问题:

  • 每个连接的Plan Cache是独立的,无法共享。

  • 每个连接都会缓存一份Plan Cache,导致内存占用较多。

PolarDB PostgreSQL版(兼容Oracle)引入了全局执行计划缓存(简称GPC)功能,通过让不同的连接共享同一份Plan Cache来解决以上两个问题。

Plan可以在不同的Prepared Statement、连接之间共享。对于有大量不同SQL的应用程序,GPC可以大大降低内存的使用量,减少OOM(Out of Memory)的风险。 此外更高效的Plan Cache机制减少了生成执行计划的代价,因此性能也有所提升。

Plan共享的前提是它们的Query Key是一致的,Query Key组成包括以下几部分:

  • 查询文本。

  • 数据库标识号。

  • 对象搜索路径。

  • 用户ID。

前提条件

  • PolarDB PostgreSQL版(兼容Oracle)集群默认开启GPC功能。

  • 支持的PolarDB PostgreSQL版(兼容Oracle)的版本如下:

    Oracle 2.0(内核小版本2.0.14.15.0及以上)

    说明

    您可通过如下语句查看PolarDB PostgreSQL版(兼容Oracle)的内核小版本的版本号:

    SHOW polar_version; 

使用限制

  • 仅支持Prepared Statement形式的查询,即不支持PL/SQL场景下的Plan Cache。

  • 仅支持SELECTINSERTUPDATEDELETE语句。

  • 不支持临时表。

参数说明

参数

说明

polar_gpc_mem

用于设置存放GPC的内存大小。单位:MB。默认值为30 MB,取值不超过shared_buffer的数量。

说明
  • 参数修改后需要重启集群才能生效。

  • polar_gpc_mem小于等于0时,表示关闭GPC功能;polar_gpc_mem大于0时,集群在启动时会预留此时设置的共享内存。当共享内存不足时,新的Plan Cache会暂时存放到本地。当不经常使用或者失效的GPC被清理以后,会释放出共享内存空间,之后本地的Plan Cache会尝试移动到GPC中。

polar_enable_gpc_level

GPC功能的开启级别,允许动态修改。取值如下:

  • 0(默认):表示不使用GPC。

  • 1:表示仅在只读节点(RO)上使用GPC。

  • 2:表示在主节点(RW)和只读节点上都使用GPC。

说明
  • 该参数必须与polar_gpc_mem配合使用,只有 polar_gpc_mem大于0且polar_enable_gpc_level大于0时,GPC才能正常工作。

  • 如果polar_gpc_mem大于0, 而polar_enable_gpc_level等于0,那么已经使用了GPC的查询可以继续使用,但是新的查询不会继续使用GPC。

polar_gpc_clean_timeout

清理不经常用GPC的时间间隔,可以动态修改,单位:秒。默认值为1800s,取值范围为0~24小时之间的数值。

polar_worker.gpc_clear_interval

清理失效GPC的时间间隔,可以动态修改,单位:秒。默认值为60秒,最大允许设置为 (2^32 - 1)/1000。

polar_gpc_clean_max

一次清理的GPC数量,可以动态修改。默认值为100,取值范围为10~10000之间的数值。

polar_gpc_partitions

用于保存GPC的哈希表数量。默认值为32,取值范围为1~1024之间的数值。

说明

参数修改后需要重启才能生效。

polar_gpc_entries

每个哈希表中的最大条目数量。默认值为1024,取值范围为1~10000之间的数值。

说明

参数修改后需要重启才能生效。

使用指南

polar_stat_gpc

通过polar_stat_gpc视图可以查看GPC的整体使用状况。使用方法如下:

SELECT * FROM polar_stat_gpc;

polar_stat_gpc视图中主要指标如下:

  • get:尝试匹配GPC的次数。

  • hit:成功匹配到GPC的次数。

  • store:GPC保存成功的次数。

  • store_failed:因为暂时的GPC内存不足导致的保存失败次数。如果该值经常上升,说明polar_gpc_mem设置小了。

  • store_exists:尝试将Local Plan Cache添加到GPC时,发现其他Session已经写入该Plan的次数。

polar_gpc_plan

通过polar_gpc_plan视图可以查看每一个GPC占用的内存情况。使用方法如下:

SELECT * FROM polar_gpc_plan;

polar_gpc_plan视图中主要指标如下:

  • plan_id:执行计划的ID。

  • stmt_name:Prepared Statement的名称。

  • query:查询语句。

  • used_cnt:该计划被使用的次数。

  • last_use_time:上次使用该GPC的时间。

  • is_valid:计划是否有效。

polar_gpc_plan_mcxt

通过polar_gpc_plan_mcxt视图可以查看每一个GPC的MemoryContext信息。使用方法如下:

SELECT * FROM polar_gpc_plan_mcxt;

polar_gpc_plan_mcxt视图中主要指标如下:

  • plan_id:执行计划的ID。

  • mcxt_name:MemoryContext的名称。

  • totalspace:总共的内存空间。

  • freespace:剩余的内存空间。

  • used:使用的内容空间。

  • nblocks:block的数量。

polar_gpc_plan_key

通过polar_gpc_plan_key视图可以查看每个GPC的GPC Key(用于匹配GPC的键)。使用方法如下:

SELECT * FROM polar_gpc_plan_key;

polar_gpc_plan_key视图中主要指标如下:

  • plan_id:计划的ID。

  • query:查询语句。

  • dbid:数据库的ID。

  • pid:进程号。

  • num_params:查询语句的参数个数。

  • search_path:搜索路径。

  • role_id:用户ID。

polar_prepared_statement

通过polar_prepared_statement视图可以查看GPC中所有的Prepared Statement信息。使用方法如下:

SELECT * FROM polar_prepared_statement;

polar_prepared_statement视图中主要指标如下:

  • is_saved:Prepared Statement的执行计划是否保存到了GPC。

  • is_valid:计划是否有效。

  • cacheable:计划是否可以缓存。

polar_gpc_evict_invalid_gpc

通过polar_gpc_evict_invalid_gpc函数可以手动清理已经失效的GPC。使用方法如下:

SELECT polar_gpc_evict_invalid_gpc();

如果不手动调用该函数,系统默认每隔$polar_worker.gpc_clear_interval秒自动清理一次失效的GPC。

polar_gpc_evict_live_gpc

通过polar_gpc_evict_live_gpc函数可以手动淘汰一些最近不常用的GPC。使用方法如下:

SELECT polar_gpc_evict_live_gpc(); 

如果不手动调用该函数,系统默认每隔$polar_worker.gpc_clear_interval秒自动淘汰不常用的GPC。